//
//  EDSortedArrayExtension.m
//  histoval
//
//  Created by Daniel Braun on 17/06/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "EDSortedArrayExtension.h"

#include "objcExt.h"

#import "EDSortedArray+Private.h"


@implementation NSEnumerator (DBExtensions)
- (id) prevObject // only for enumerator of EDSortedArray
{
	NSAssert(0, @"prevObject only valid for _EDSortedArrayEnumerator");
	return nil;
}
@end



@interface EDSortedArray (DBPrivateExtensions)

- (EDRedBlackTreeNode *)_predecessorForNode:(EDRedBlackTreeNode *)x;

@end

@interface _EDSortedArrayEnumerator (DBExtensions)
- (id) prevObject; // only for enumerator of EDSortedArray
- (void) _setNode:(EDRedBlackTreeNode *)n;
@end


@implementation _EDSortedArrayEnumerator (DBExtensions)
- (id) prevObject
{
	id object;
	
	if(NIL(node) == YES) return nil;
	object = node->object;
	node = [array _predecessorForNode:node];
	
	return object;
}
- (void) _setNode:(EDRedBlackTreeNode *)n
{
	node=n; // no retain in enumerator in EDSortedArray.m
}

@end



@implementation EDSortedArray (DBPrivateExtensions)

- (EDRedBlackTreeNode *)_predecessorForNode:(EDRedBlackTreeNode *)x
{
	EDRedBlackTreeNode *y;
	
	if(NIL(x->left) == NO) {
		return [self _maximumBelowNode:x->left];
	}
	((EDRedBlackTreeNode *)sentinel)->left = NULL; // to make sure
	y = x->parent;
	while(x == y->left)
	{
		x = y;
		y = y->parent;
	}
	return y;
}



@end


@implementation  EDSortedArray (DBExtensions)
- (void)encodeWithCoder:(NSCoder *)coder
{
	//[super encodeWithCoder:coder];
	if ( [coder allowsKeyedCoding] ) {
		[coder encodeObject:[self allObjects] forKey:@"content"];
		SEL s=[self comparisonSelector];
		[coder encodeObject:[NSString stringWithCString:sel_getName(s)] forKey:@"selector"];
	}
}

- (id) initWithCoder:(NSCoder *) coder
{
	//self=[super initWithCoder:coder];
	self=[self init];
	if ([coder allowsKeyedCoding]) {
		NSArray *content=[coder decodeObjectForKey:@"content"];
		NSString *s=[coder decodeObjectForKey:@"selector"];
		if (!s || !content) goto failed;
		SEL sel=selFromString(s);
		if (!sel) goto failed;
		self=[self initWithComparisonSelector:sel];
		[self addObjectsFromArray:content];
		return self;
	}
failed:
	[self release];
	return nil;
}
- (id)predecessorForObject:(id)anObject
{
	EDRedBlackTreeNode *x, *y;
	
	x = [self _nodeForObject:anObject];
	if(NIL(x) == YES)
		[NSException raise:NSInvalidArgumentException format:@"-[%@ %@]: Attempt to retrieve successor for an object that is not in the tree.", NSStringFromClass(isa), NSStringFromSelector(_cmd)];
	
	y = [self _predecessorForNode:x];
	
	return y->object;
}

- (NSEnumerator *)objectEnumeratorForSmallerOrEqualMember:(id)anObject
{
	_EDSortedArrayEnumerator *e=[[[_EDSortedArrayEnumerator alloc] initWithSortedArray:self] autorelease];
	if (!e) return nil;
	EDRedBlackTreeNode *x=[self _nodeForObjectOrPredecessorOfObject:anObject];
	if (!x) return nil;
	[e _setNode:x];
	return e;
}
@end


